package com.linkme2night.controller;

import java.util.HashMap;
import java.util.LinkedList;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.RatingBar;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.linkme2night.R;
import com.linkme2night.model.Venue;

public class GoogleMapAPI {

	private static final LatLng WROCLAW = new LatLng(51.110056, 17.032079);
	private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1; 
	private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000000;

	private Location clubber_location;
	private GoogleMap venues_map;
	private Activity activity;
	private MapFragment map_frag;
	private Circle circle;
	private HashMap<String, Venue> markers;
	private LinkedList<Marker> markers_obj;
	private Marker location_marker;

	public GoogleMapAPI(final Activity activity)
	{
		markers = new HashMap<String, Venue>();
		markers_obj = new LinkedList<Marker>();

		this.activity = activity;
		map_frag = (MapFragment) this.activity.getFragmentManager().findFragmentById(R.id.venues_map);
		venues_map = map_frag.getMap();

		venues_map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
		venues_map.moveCamera(CameraUpdateFactory.newLatLng(WROCLAW));
		venues_map.animateCamera(CameraUpdateFactory.zoomTo(16), 2000, null);

		circle = venues_map.addCircle(new CircleOptions()
		.center(WROCLAW)
		.radius(0)
		.fillColor(0x320000bb)
		.strokeColor(0x640000bb)
		.strokeWidth(3.0f)
		);

		venues_map.setInfoWindowAdapter(new InfoWindowAdapter() {

			// Use default InfoWindow frame
			@Override
			public View getInfoWindow(Marker marker) {              
				return null;
			}           

			// Defines the contents of the InfoWindow
			@Override
			public View getInfoContents(Marker marker) {
				Venue venue = markers.get(marker.getId());
				// Getting view from the layout file map_marker_info_window
				View v = activity.getLayoutInflater().inflate(R.layout.map_marker_info_window, null);
				TextView text = (TextView) v.findViewById(R.id.venue_text);
				text.setText("Club: " + venue.getName() + "\nAddress: " + venue.getAddress());
				RatingBar marker_rating = (RatingBar) v.findViewById(R.id.marker_rating);
				marker_rating.setRating(venue.getRanking());
				return v;
			}
		});

		venues_map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

			@Override
			public void onInfoWindowClick(Marker marker)
			{
				FrontController.openInteractWithVenue(activity.getApplicationContext(), markers.get(marker.getId()).getID(), 1);		
			}
		});
	}

	/**
	 * sets the current radius on the map in meters.
	 * If radius == 0, then the circle disappears
	 * @param radius
	 */
	public void setRadius(double radius)
	{
		float[] results = new float[3];
		circle.setCenter(new LatLng(clubber_location.getLatitude(), clubber_location.getLongitude()));
		circle.setRadius(radius);

		for(int i=0; i<markers_obj.size(); i++)
		{
			Location.distanceBetween(clubber_location.getLatitude(), clubber_location.getLongitude(),
					markers_obj.get(i).getPosition().latitude, markers_obj.get(i).getPosition().longitude, results);
			if(results[0] > radius)
				markers_obj.get(i).setVisible(false);
			else
				markers_obj.get(i).setVisible(true);
		}
	}

	public void locateMe()
	{
		int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity.getBaseContext());
		// Showing status
		if(status!=ConnectionResult.SUCCESS) // Google Play Services are not available
		{ 
			int requestCode = 10;
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, activity, requestCode);
			dialog.show();

		}
		else  // Google Play Services are available
		{
			// Enabling MyLocation Layer of Google Map
			//venues_map.setMyLocationEnabled(true);
			// Getting LocationManager object from System Service LOCATION_SERVICE
			LocationManager locationManager = (LocationManager)activity.getSystemService(Context.LOCATION_SERVICE);
			// Creating a criteria object to retrieve provider

			Criteria criteria = new Criteria();
			// Getting the name of the best provider
			String provider = locationManager.getBestProvider(criteria, true);
			// Getting Current Location
			clubber_location = locationManager.getLastKnownLocation(provider);
			LocationListener locationListener = new LocationListener()
			{
				@Override
				public void onLocationChanged(Location location_changed) 
				{

				}

				@Override
				public void onProviderDisabled(String provider) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onProviderEnabled(String provider) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onStatusChanged(String provider, int status,
						Bundle extras) {
					// TODO Auto-generated method stub

				}
			};
			locationManager.requestLocationUpdates(provider, MINIMUM_TIME_BETWEEN_UPDATES,MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, locationListener);
			clubber_location = locationManager.getLastKnownLocation(provider);
			
			if(clubber_location!=null)
			{
				//PLACE THE INITIAL MARKER   
				if(location_marker != null)
					location_marker.setVisible(false);
				
				location_marker = venues_map.addMarker(new MarkerOptions()
				.position(new LatLng(clubber_location.getLatitude(), clubber_location.getLongitude()))
				.icon(BitmapDescriptorFactory.fromResource(R.drawable.user_position))
				.visible(true));

				venues_map.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(clubber_location.getLatitude(), clubber_location.getLongitude())), 1000, null);
			}
		}
	}

	public void addMarker(Venue venue)
	{
		Marker new_marker = venues_map.addMarker(new MarkerOptions()
		.position(new LatLng(venue.getLatitude(), venue.getLongitude()))
		.icon(BitmapDescriptorFactory.fromResource(R.drawable.yellow_point)));

		markers_obj.add(new_marker);
		markers.put(new_marker.getId(), venue);
	}
}

